package edu.scut.course_management.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import edu.scut.course_management.filter.LoginAuthenticationFilter;
import edu.scut.course_management.handler.AnonymousAccessHandler;
import edu.scut.course_management.handler.LoginFailHandler;
import edu.scut.course_management.handler.LoginSuccessHandler;
import edu.scut.course_management.handler.LogoutHandler;
import edu.scut.course_management.handler.NoPermissionHandler;
import edu.scut.course_management.service.PersonManagementService;

/**
 * Spring Security核心配置类：WebSecurityConfig
 * 配置权限控制，异常处理
 * @author sherry
 */

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    PersonManagementService personService;  //人事管理服务
    @Autowired
    AnonymousAccessHandler anonymousAccessHandler; //匿名访问处理器
    @Autowired
    LogoutHandler logoutHandler; // 登出处理器
    @Autowired
    LoginSuccessHandler loginSuccessHandler;  // 登录成功处理器
    @Autowired
    LoginFailHandler loginFailHandler;  // 登录失败处理器
    @Autowired
    NoPermissionHandler noPermissionHandler; // 权限不足处理器

    /**
     * 配置用户获取方式
     * 配置密码加密方式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 密码加密方式，添加用户时候需要适配
        // auth.userDetailsService(personService).passwordEncoder(new BCryptPasswordEncoder());
        auth.userDetailsService(personService).passwordEncoder(new BCryptPasswordEncoder());

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        //http相关的配置，包括登入登出、异常处理、会话管理

        // http.authorizeRequests().anyRequest().permitAll()
        //     .and().httpBasic()
        //     .and().csrf().disable(); // 关闭csrf验证(防止跨站请求伪造攻击)

        http.authorizeRequests().anyRequest().authenticated()
            .and().httpBasic()
            .and().csrf().disable() // 关闭csrf验证(防止跨站请求伪造攻击)
            .exceptionHandling().authenticationEntryPoint(anonymousAccessHandler)  // 匿名访问处理器
            .and().logout().logoutUrl("/Authentication/Logout").logoutSuccessHandler(logoutHandler).deleteCookies("JSESSIONID"); // 登出处理器
        http.addFilterAt(loginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); // 登录处理器
        http.exceptionHandling().accessDeniedHandler(noPermissionHandler);   //权限处理器

    }

    // 自定义登录认证过滤器
    @Bean
    LoginAuthenticationFilter loginAuthenticationFilter() throws Exception {
        LoginAuthenticationFilter loginAuthenticationFilter = new LoginAuthenticationFilter();
        loginAuthenticationFilter.setFilterProcessesUrl("/Authentication/Login");
        loginAuthenticationFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
        loginAuthenticationFilter.setAuthenticationFailureHandler(loginFailHandler);
        loginAuthenticationFilter.setAuthenticationManager(super.authenticationManagerBean());
        return loginAuthenticationFilter;
    }
}
